로딩 중이에요... 🐣
09 포스트 생성 API 작업 | ✅ 편저: 코담 운영자
9강 - 포스트 생성 API 작업
생성 API 작업✨ 이번 강의 목표
- 사용자가 게시물을 작성하고 업로드할 수 있는 API 구현
- GET/POST 방식 분기 처리 흐름 구현
- 로그인 인증 유무에 따라 접근 제어
- 파일 업로드(
request.FILES
) 및 데이터 저장 이해
1. 프로젝트 개요
Django를 기반으로 사용자가 게시글(이미지 + 글)을 등록할 수 있도록 하는 기능을 구현합니다. Cookiecutter로 생성된 Instagram 클론 프로젝트이며, 로그인한 사용자만 게시글 작성이 가능합니다.
2. URL 설정
✅ 설명
게시물 생성을 위한 URL 경로를 설정합니다. /create/
경로로 접근 시 post_create 뷰가 호출됩니다. name='post_create'
는 템플릿에서 {% url 'posts:post_create' %}
로 쉽게 참조할 수 있도록 합니다.
posts/urls.py
from django.urls import path
from . import views
app_name = "posts"
urlpatterns = [
path('', views.index, name="index"), # 메인 페이지
path('create/', views.post_create, name='post_create') # 게시물 생성 페이지
]
post_create
URL을 통해 게시물 생성 뷰로 접근합니다.
3. 게시물 생성 버튼 템플릿
<!-- 게시물 생성 버튼 -->
<div class="cursor-pointer transform transition-transform duration-300 hover:scale-110">
<a href="{% url 'posts:post_create' %}">
<i class="fa fa-plus-circle text-gray-600 hover:text-blue-500 text-2xl"></i>
</a>
</div>
상단 header.html에서 해당 버튼 클릭 시 게시글 생성 페이지로 이동합니다.
4. 게시물 생성 템플릿 (create.html)
✅ 설명
사용자가 입력할 수 있는 폼을 HTML로 구성합니다. 입력 항목은 이미지 파일과 캡션(내용)입니다. TailwindCSS를 사용해 UI 구성도 깔끔하게 디자인되어 있습니다.
form
태그의enctype="multipart/form-data"
는 파일 업로드 시 필수csrf_token
은 보안상 필수 요소로 POST 요청 위조 방지에 사용됩니다textarea
와file input
은 각각 caption과 image 입력용
templates/posts/post_create.html
{% extends "posts/base.html" %}
{% load static %}
{% block title %} 포스트 생성 {% endblock title %}
{% block content %}
<div class="flex justify-center items-center min-h-screen bg-gray-100">
<div class="w-3/4 aspect-[4/3] bg-white rounded-lg shadow-md p-8">
<h1 class="text-2xl font-bold text-gray-800 mb-6 text-center">게시글 등록</h1>
<!-- 게시물 등록 폼 -->
<form action="{% url 'posts:post_create' %}" method="post" enctype="multipart/form-data" class="space-y-6 w-4/6 mx-auto">
{% csrf_token %}
<div>
<label for="id_caption" class="block text-sm font-medium text-gray-700 mb-1">내용</label>
<textarea id="id_caption" name="caption" class="w-full border-gray-300 rounded-lg shadow-sm focus:border-indigo-500 focus:ring-indigo-500" rows="12" required></textarea>
</div>
<div>
<label for="id_image" class="block text-sm font-medium text-gray-700 mb-1">사진</label>
<input required id="id_image" type="file" name="image" class="w-full file:mr-4 file:py-2 file:px-4 file:rounded-lg file:border-0 file:bg-indigo-600 file:text-white file:font-medium file:cursor-pointer file:hover:bg-indigo-500" />
</div>
<button type="submit" class="w-full bg-indigo-600 text-white font-semibold rounded-lg py-3 text-center shadow-md hover:bg-indigo-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">등록하기</button>
</form>
</div>
</div>
{% endblock content %}
enctype="multipart/form-data"
필수이며, CSRF 토큰도 꼭 포함합니다.
5. 게시물 생성 뷰
✅ 설명
클라이언트 요청이 GET인지 POST인지에 따라 다른 처리를 합니다. GET 요청이면 업로드 폼을 보여주고, POST 요청이면 실제 데이터를 저장합니다.
request.user.is_authenticated
: 로그인된 사용자인지 검사get_object_or_404
: 로그인 사용자의 유효성 검사 및 조회request.FILES['image']
: 업로드된 이미지 파일 추출request.POST['caption']
: 사용자가 입력한 글 내용 추출Post.objects.create(...)
: Post 모델 객체를 DB에 저장- 저장 후
redirect('posts:index')
로 메인 피드로 이동
인증되지 않은 사용자는 강제로 로그인 페이지로 이동됩니다
posts/views.py
from django.shortcuts import render, get_object_or_404, redirect
from django_instagram.users.models import User as user_model
from . import models
# 메인 페이지
def index(request):
return render(request, 'posts/index.html')
# 게시물 생성 뷰
def post_create(request):
if request.method == "GET":
return render(request, 'posts/post_create.html')
elif request.method == "POST":
if request.user.is_authenticated:
user = get_object_or_404(user_model, pk=request.user.id)
image = request.FILES['image']
caption = request.POST['caption']
# 게시물 저장
new_post = models.Post.objects.create(
author=user,
image=image,
caption=caption,
)
new_post.save()
return redirect('posts:index')
else:
return redirect('users:login')
인증되지 않은 사용자가 접근할 경우 로그인 페이지로 리디렉션됩니다.
6. 게시물 생성 전체 흐름 요약
✅ 설명
사용자가 게시물을 생성할 때 어떤 요청과 응답이 오가는지 전체적인 흐름을 순서대로 설명합니다. 실제 실무에서도 API 동작 흐름을 먼저 파악하고 뷰를 작성해야 합니다.
- 로그인된 사용자가 "+" 버튼 클릭
post_create
URL로 이동- GET 요청 시 → post_create.html 렌더링
- POST 요청 시 → 폼 데이터 수신 및 저장
- 업로드된 이미지 파일은
request.FILES['image']
에서 가져옴 - 텍스트 내용은
request.POST['caption']
에서 가져옴 - 저장 후 → 메인 피드(
posts:index
)로 리디렉션
✅ 정리
- 로그인 인증 여부 체크 (
request.user.is_authenticated
) request.FILES
는 파일 업로드를 처리하기 위한 전용 객체form
에는 반드시enctype="multipart/form-data"
필요- 게시물 저장 후 redirect로 리다이렉트하여 UX 흐름 유지
👉 다음 강의에서는 실제 모델 구조를 기반으로 업로드 이미지의 미디어 처리 및 피드에 출력하는 기능을 구현합니다.